package ru.aslanov.schedule.server.gcalendar;

import com.google.gdata.client.http.AuthSubUtil;
import ru.aslanov.schedule.model.GoogleCalendarSync;
import ru.aslanov.schedule.model.Schedule;
import ru.aslanov.schedule.server.AccessDeniedException;
import ru.aslanov.schedule.server.AccessManager;
import ru.aslanov.schedule.server.PMF;
import ru.aslanov.schedule.utils.JSUtil;

import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by IntelliJ IDEA.
 * Created: Mar 3, 2010 6:03:30 PM
 *
 * @author Sergey Aslanov
 */
public class GCalendarAuthorizeServlet extends HttpServlet {
    private static final Logger log = Logger.getLogger(GCalendarAuthorizeServlet.class.getName());

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String scheduleKey = request.getParameter("schedule");
        String callback = request.getParameter("callback");

        final AccessManager am = AccessManager.getInstance();
        try {
            am.checkScheduleAdmin(scheduleKey);
        } catch (AccessDeniedException e) {
            throw new ServletException(e);
        }

        String token = request.getParameter("next");
        if (token == null) {
            String requestUrl = AuthSubUtil.getRequestUrl(request.getRequestURL()
                    .append("?").append(request.getQueryString()).append("&next=1").toString(),
                    "http://www.google.com/calendar/feeds/", false, true);
            response.sendRedirect(requestUrl);
        } else {
            try {
                String onetimeUseToken = AuthSubUtil.getTokenFromReply(request.getQueryString());
                if (onetimeUseToken == null) 
                    throw new Exception("Access rejected");
                log.info("Received token: " + onetimeUseToken);

                String sessionToken = AuthSubUtil.exchangeForSessionToken(URLDecoder.decode(onetimeUseToken, "UTF-8"), null);
                if (sessionToken == null)
                    throw new Exception("Access rejected");
                log.info("Got session token: " + sessionToken);

                final PersistenceManager pm = PMF.getThreadLocalPersistenceManager();
                final Transaction tran = pm.currentTransaction();

                try {
                    tran.begin();

                    final Schedule schedule = pm.getObjectById(Schedule.class, scheduleKey);
                    GoogleCalendarSync googleCalendarSync = schedule.getGoogleCalendarSync();
                    if (googleCalendarSync == null) {
                        googleCalendarSync = new GoogleCalendarSync();
                        schedule.setGoogleCalendarSync(googleCalendarSync);
                    }
                    googleCalendarSync.setSessionToken(sessionToken);
                    googleCalendarSync.setAuthorizedByUser(am.getEmail());

                    tran.commit();
                } finally {
                    if (tran.isActive()) tran.rollback();
                    //pm.close();
                }

                printResult(response.getWriter(), callback, true, null);
            } catch (Exception e) {
                log.log(Level.SEVERE, "Error publishing to gCal", e);
                printResult(response.getWriter(), callback, false, e.toString());
            }
        }
    }

    private void printResult(PrintWriter writer, String callback, boolean success, String message) throws IOException {
        JSUtil.printResponse(writer, callback, true, true,
                new JSUtil.Param("success", success),
                new JSUtil.Param("message", message));
    }

}
